package com.sdy.hospitalguard.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.model.FileObj;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.StringUtil;
import com.sdy.hospitalguard.biz.constants.RedisConstants;
import com.sdy.hospitalguard.biz.dto.PatientDTO;
import com.sdy.hospitalguard.biz.dto.PatientDetailsDTO;
import com.sdy.hospitalguard.biz.dto.PatientPcDTO;
import com.sdy.hospitalguard.biz.dto.VisitRecordDTO;
import com.sdy.hospitalguard.biz.mapper.PatientInformationMapper;
import com.sdy.hospitalguard.biz.model.*;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import com.sdy.redis.service.RedisService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.sdy.mvc.utils.HttpUtil.getUserId;

/**
 * <p>
 * 患者登记表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2020-05-08
 */
@Slf4j
@Service
public class PatientInformationServiceImpl extends BaseServiceImpl<PatientInformation> implements PatientInformationService {
    @Autowired
    private PatientInformationMapper patientInformationMapper;
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private QrcodeService qrcodeService;
    @Autowired
    private BuildingService buildingService;
    @Autowired
    private MatchingPeopleService matchingPeopleService;
    @Autowired
    private SickbedService sickbedService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private RegulationsService regulationsService;
    @Autowired
    private NoticeService noticeService;

    @Override
    public PatientInformation selectPatient(PatientDTO patientDTO) throws BizException {
        Assert.isBlank(patientDTO.getAdmissionNumber(), "住院号不能为空!");
        Assert.isNull(patientDTO.getSickbedId(), "床位号不能为空!");
        LambdaQueryWrapper<PatientInformation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PatientInformation::getAdmissionNumber, patientDTO.getAdmissionNumber());
        lambdaQueryWrapper.eq(PatientInformation::getSickbedId, patientDTO.getSickbedId());
        lambdaQueryWrapper.eq(PatientInformation::getPatientState, 0);
        return getOne(lambdaQueryWrapper);
    }

    @Override
    public PatientDetailsDTO patientQuery(Integer userId) {
        return patientInformationMapper.patientQuery(userId);
    }

    @Override
    public Boolean patientRegister(PatientInformation patientInformation, Integer userId) throws BizException {
        Date date = new Date();
        patientInformation.setUserId(userId);
        patientInformation.setPatientState(0);
        patientInformation.setAdmissionTime(date);
        patientInformation.setCreateTime(date);
        boolean save = save(patientInformation);
        // 床位使用变更
        boolean update = sickbedService.update(Wrappers.<Sickbed>lambdaUpdate()
                .eq(Sickbed::getId, patientInformation.getSickbedId())
                .set(Sickbed::getState, 1));
        Assert.notTrue(update, "床位信息错误!");
        // 通行码生效(待补充)

        // 如果申请患者成功，同步数据到机器
        if (save) {
            // 申请成为患者的时候，同步有效数据到matchingPeople
            // hospitalUser数据
            HospitalUser byId = hospitalUserService.getById(userId);
            Assert.isNull(byId, "无此用户数据!");
            String path = null;
            if (StringUtils.isNotBlank(byId.getHeadPortrait())) {
                FileObj fileObj = redisService.get(RedisConstants.FILE_UPLOAD_UUID + byId.getHeadPortrait(), FileObj.class);
                path = fileObj.getPath();
            }
            // 查询二维码数据
            Qrcode qrcode = qrcodeService.getOne(Wrappers.<Qrcode>lambdaQuery()
                    .eq(Qrcode::getUserId, byId.getId()));
            // 查询是哪栋楼的患者
            Building building = buildingService.getById(patientInformation.getFloorId());
            Assert.isNull(building, "请确认正确的楼信息!");
            MatchingPeople matchingPeople = new MatchingPeople()
                    .setUserId(userId)
                    .setName(byId.getName())
                    .setCardId(byId.getIdCard())
                    .setFaceId(userId)
                    .setPhotoPath(path)
                    .setQrcodeContent(qrcode.getQrcodeContent())
                    .setRemark("患者")
                    .setBuilding(patientInformation.getFloorId())
                    .setLastChange(System.currentTimeMillis() / 1000 + "")
                    .setStatus(0);
            boolean add = matchingPeopleService.add(matchingPeople);
            Assert.notTrue(add, "matchingPeople新增陪护数据失败!");
        }
        return save;
    }

    @Override
    public Boolean patientAddRelation(HospitalUser hospitalUser, HttpServletRequest request) throws BizException {
        HospitalUser userByIdCard = hospitalUserService.getUserByIdCard(hospitalUser.getIdCard());
        Assert.isNull(userByIdCard.getIdCard(), "此用户未注册!");
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前用户失效");
        HospitalUser byId = hospitalUserService.getById(userId);
        //获取患者信息
        PatientInformation one = patientInformationService.lambdaQuery()
                .eq(PatientInformation::getUserId, userId)
                .eq(PatientInformation::getPatientState, 0)
                .one();
        boolean f = escortAssociatedService.lambdaQuery()
                .eq(EscortAssociated::getPatientId, one.getId())
                .eq(EscortAssociated::getUserId, userByIdCard.getId())
                .eq(EscortAssociated::getStatus,0)
                .in(EscortAssociated::getAttendantState, 0, 2)
                .in(EscortAssociated::getFlowState, 0, 1, 4)
                .count() > 0;
        Assert.isTrue(f, "此陪护人员已存在,请勿重复添加");
        //判断该陪护是否在陪护其他人员
        boolean c = escortAssociatedService.lambdaQuery()
                .eq(EscortAssociated::getUserId, userId)
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getStatus,0)
                .eq(EscortAssociated::getFlowState, 0)
                .count() > 0;
        //判断该患者 是否有其他正在陪护
        Integer count = escortAssociatedService.lambdaQuery()
                .eq(EscortAssociated::getPatientId, one.getId())
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getStatus,0)
                .eq(EscortAssociated::getFlowState, 0)
                .count();

        //查询规则
        String escortAssociatedCounts = regulationsService.selectEscortAssociatedRule(one.getId());
        boolean save = false;
        EscortAssociated escortAssociated = new EscortAssociated();
        escortAssociated.setPatientId(one.getId());
        escortAssociated.setUserId(userByIdCard.getId());
        escortAssociated.setCreateTime(new Date());
        //判断患者是否有其他正在陪护
        if (count > 0) {
            //有其他正在陪护
            //判断可以有多少正在陪护
            if (count >= Integer.parseInt(escortAssociatedCounts)) {
                escortAssociated.setAttendantState(2);
                escortAssociated.setFlowState(1);
                save = escortAssociatedService.save(escortAssociated);
                Assert.notTrue(save,"陪护添加失败!");
            } else {
                //可以有多陪护则添加
                //判断陪护者状态
                if (c) {
                    //陪护者有正在陪护
                    escortAssociated.setAttendantState(2);
                    escortAssociated.setFlowState(1);
                    save = escortAssociatedService.save(escortAssociated);
                    Assert.notTrue(save,"陪护添加失败!");
                    Assert.isTrue(c, "此陪护者正在陪护其他人员,已为您添加!");
                } else {
                    //陪护者无正在陪护
                    escortAssociated.setAttendantState(2);
                    escortAssociated.setFlowState(1);
                    save = escortAssociatedService.save(escortAssociated);
                    Assert.notTrue(save, "陪护添加失败!");

                    Notice one1 = noticeService.lambdaQuery()
                            .eq(Notice::getAssociationId, escortAssociated.getId())
                            .eq(Notice::getHandlerId, userByIdCard.getId())
                            .eq(Notice::getResult, 0)
                            .eq(Notice::getType, 1)
                            .one();
                    if (one1 != null) {
                        boolean b = noticeService.removeById(one1.getId());
                        Assert.notTrue(b, "删除消息失败!");
                    }
                    Notice notice = new Notice()
                            .setAssociationId(escortAssociated.getId())
                            .setSendUserId(userId)
                            .setHandlerId(userByIdCard.getId())
                            .setType(1)
                            .setState(1)
                            .setResult(0)
                            .setMessageContent(byId.getName() + "向你发起陪护关联")
                            .setCreateTime(new Date());
                    boolean save1 = noticeService.save(notice);
                    Assert.notTrue(save1, "消息发送失败");
                }
            }
        } else {
            //患者无正在陪护
            if (c) {
                //陪护者有正在陪护
                escortAssociated.setAttendantState(2);
                escortAssociated.setFlowState(1);
                save = escortAssociatedService.save(escortAssociated);
                Assert.isTrue(c, "此陪护者正在陪护其他人员,已为您添加!");
            } else {
                //陪护者无正在陪护
                escortAssociated.setAttendantState(2);
                escortAssociated.setFlowState(1);
                save = escortAssociatedService.save(escortAssociated);
                Assert.notTrue(save, "陪护添加失败!");

                Notice one1 = noticeService.lambdaQuery()
                        .eq(Notice::getAssociationId, escortAssociated.getId())
                        .eq(Notice::getHandlerId, userByIdCard.getId())
                        .eq(Notice::getResult, 0)
                        .eq(Notice::getType, 1)
                        .one();
                if (one1 != null) {
                    boolean b = noticeService.removeById(one1.getId());
                    Assert.notTrue(b, "删除消息失败!");
                }
                Notice notice = new Notice()
                        .setAssociationId(escortAssociated.getId())
                        .setSendUserId(userId)
                        .setHandlerId(userByIdCard.getId())
                        .setType(1)
                        .setState(1)
                        .setResult(0)
                        .setMessageContent(byId.getName() + "向你发起陪护关联")
                        .setCreateTime(new Date());
                boolean save1 = noticeService.save(notice);
                Assert.notTrue(save1, "消息发送失败");
            }
        }
        return true;
    }

//    public Boolean switchEscort(HttpServletRequest request, Integer type, Integer escortId){
//
//    }

    @Override
    public Page<PatientPcDTO> patienPageQuery(Page page, String content, Integer areaId, String startDate ,String endDate) {
        if (StringUtil.isNotBlank(startDate)){
            startDate = startDate + " 00:00:00";
        }
        if (StringUtil.isNotBlank(endDate)){
            endDate = endDate + " 23:59:59";
        }
        return patientInformationMapper.patienPageQuery(page, content, areaId, startDate, endDate);
    }

    @Override
    public List<PatientPcDTO> patienPageQuery(String content, Integer areaId, String startDate ,String endDate) {
        if (StringUtil.isNotBlank(startDate)){
            startDate = startDate + " 00:00:00";
        }
        if (StringUtil.isNotBlank(endDate)){
            endDate = endDate + " 23:59:59";
        }
        return patientInformationMapper.patienPageQuery(content, areaId, startDate, endDate);
    }

    @Override
    public PatientPcDTO patienDetails(Integer id) {
        return patientInformationMapper.patienDetails(id);
    }

    @Override
    public List<HospitalUser> patienEscortList(Integer id) {
        return patientInformationMapper.patienEscortList(id);
    }

    @Override
    public Page<VisitRecordDTO> patienVisitPage(Page page,Integer id) {
        return patientInformationMapper.patienVisitPage(page,id);
    }
}
